package com.springboot.ball.consumer.games;

import com.alibaba.fastjson.JSONObject;
import com.springboot.ball.consumer.WebSocketServer;

import java.util.concurrent.locks.ReentrantLock;

public class Game extends Thread{
    // 默认宽高，但实际会使用前端canvas的尺寸
    private static final int DEFAULT_WIDTH = 1000;
    private static final int DEFAULT_HEIGHT = 600;
    
    // 游戏参数常量
    private static final double PLAYER_RADIUS = 40.0; // 固定玩家半径为20
    private static final double PLAYER_SPEED = 60.0;  // 固定玩家速度为10
    private static final double FIREBALL_DAMAGE = 20.0; // 固定火球伤害为20，5次攻击会消失
    
    private final int width;
    private final int height;
    private final int [][] g;
    private final Player playerA, playerB, playerC;
    private Integer nextStepA=null;
    private Integer nextStepB=null;
    private Integer nextStepC=null;
    private String status = "playing";  // playing -> finished
    private String loser = "";  // all: 平局，A: A输，B: B输

    private ReentrantLock lock = new ReentrantLock();//读写冲突，只要有写就有冲突

    public Game(Integer idA, Integer idB, Integer idC){
        // 使用默认尺寸，前端会根据canvas尺寸调整
        this.width = DEFAULT_WIDTH;
        this.height = DEFAULT_HEIGHT;
        this.g = new int[width][height];
        
        // 所有玩家初始位置都在屏幕中间，使用固定参数
        this.playerA = new Player(idA, width/2, height/2, PLAYER_RADIUS, PLAYER_SPEED, true, new java.util.ArrayList<>(), 0, 0);
        this.playerB = new Player(idB, width/2, height/2, PLAYER_RADIUS, PLAYER_SPEED, true, new java.util.ArrayList<>(), 0, 0);
        this.playerC = new Player(idC, width/2, height/2, PLAYER_RADIUS, PLAYER_SPEED, true, new java.util.ArrayList<>(), 0, 0);
    }

    public void createMap (){
        for (int i = 0; i < width; i++) {
            for (int j = 0; j < height; j++) {
                g[i][j] = 0;
            }
        }
    }
    public int [][] getG() {
        return g;
    }

    public Player getPlayerA() {
        return playerA;
    }

    public Player getPlayerB() {
        return playerB;
    }

    public Player getPlayerC() {
        return playerC;
    }

    public void setNextStepA(int tx, int ty) {
        lock.lock();
        try {
            // 计算移动方向（示例逻辑）
            double dx = tx - playerA.getX();
            double dy = ty - playerA.getY();
            double distance = Math.sqrt(dx * dx + dy * dy);
            if (distance > 0) {
                playerA.setVx(dx / distance * playerA.getSpeed());
                playerA.setVy(dy / distance * playerA.getSpeed());
            }
        } finally {
            lock.unlock();
        }
    }

   public void setNextStepB(int tx, int ty){
        lock.lock();
        try {
            double dx = tx - playerB.getX();
            double dy = ty - playerB.getY();
            double distance = Math.sqrt(dx * dx + dy * dy);
            if(distance>0){
                playerB.setVx(dx / distance * playerB.getSpeed());
                playerB.setVy(dy / distance * playerB.getSpeed());
            }
        }finally {
            lock.unlock();
        }
   }

    public void setNextStepC(int tx, int ty){
        lock.lock();
        try {
            double dx = tx - playerC.getX();
            double dy = ty - playerC.getY();
            double distance = Math.sqrt(dx * dx + dy * dy);
            if(distance>0){
                playerC.setVx(dx / distance * playerC.getSpeed());
                playerC.setVy(dy / distance * playerC.getSpeed());
            }
        }finally {
            lock.unlock();
        }
    }
    
    // 处理玩家使用技能
    public void playerUseSkill(Player player, String skillType, int targetX, int targetY) {
        lock.lock();
        try {
            if ("fireball".equals(skillType)) {
                // 在此发送技能信息到所有客户端，但不计算伤害，由前端计算碰撞和伤害
                JSONObject resp = new JSONObject();
                resp.put("event", "skill");
                resp.put("player_id", player.getId());
                resp.put("skill_type", skillType);
                resp.put("target_x", targetX);
                resp.put("target_y", targetY);
                resp.put("source_x", player.getX());
                resp.put("source_y", player.getY());
                resp.put("damage", FIREBALL_DAMAGE); // 添加伤害信息，让前端知道伤害值
                sendAllMessage(resp.toJSONString());
            }
        } finally {
            lock.unlock();
        }
    }

    // 处理玩家死亡
    public void playerDeath(String playerIdentifier) {
        lock.lock();
        try {
            // 记录哪个玩家死亡
            if ("A".equals(playerIdentifier)) {
                // 玩家A死亡
                playerA.setHealth(0);
            } else if ("B".equals(playerIdentifier)) {
                // 玩家B死亡
                playerB.setHealth(0);
            } else if ("C".equals(playerIdentifier)) {
                // 玩家C死亡
                playerC.setHealth(0);
            }
            
            // 检查游戏是否结束
            checkGameOver();
        } finally {
            lock.unlock();
        }
    }
    
    // 检查游戏是否结束
    private void checkGameOver() {
        int aliveCount = 0;
        Player lastAlivePlayer = null;
        
        // 检查玩家A
        if (playerA.isAlive()) {
            aliveCount++;
            lastAlivePlayer = playerA;
        }
        
        // 检查玩家B
        if (playerB.isAlive()) {
            aliveCount++;
            lastAlivePlayer = playerB;
        }
        
        // 检查玩家C
        if (playerC.isAlive()) {
            aliveCount++;
            lastAlivePlayer = playerC;
        }
        
        // 只剩一名玩家，游戏结束
        if (aliveCount == 1 && lastAlivePlayer != null) {
            status = "finished";
            
            // 更明确地标识胜利者和失败者
            if (lastAlivePlayer.getId().equals(playerA.getId())) {
                // A是胜利者，BC是失败者
                loser = "BC";
                playerB.setHealth(0); // 确保失败者生命值为0
                playerC.setHealth(0);
            } else if (lastAlivePlayer.getId().equals(playerB.getId())) {
                // B是胜利者，AC是失败者
                loser = "AC";
                playerA.setHealth(0);
                playerC.setHealth(0);
            } else {
                // C是胜利者，AB是失败者
                loser = "AB";
                playerA.setHealth(0);
                playerB.setHealth(0);
            }
            
            // 发送结果
            sendResult();
            
            // 发送最终的健康同步，确保客户端显示正确
            checkHealthSync();
        } else if (aliveCount == 0) {
            // 所有玩家都死亡，平局
            status = "finished";
            loser = "all";
            sendResult();
        }
    }
    
    public void sendAllMessage(String message){//向三个client传递信息
        // 为每个玩家添加null检查
        WebSocketServer serverA = WebSocketServer.users.get(playerA.getId());
        WebSocketServer serverB = WebSocketServer.users.get(playerB.getId());
        WebSocketServer serverC = WebSocketServer.users.get(playerC.getId());
        
        if (serverA != null) serverA.sendMessage(message);
        if (serverB != null) serverB.sendMessage(message);
        if (serverC != null) serverC.sendMessage(message);
    }
    
    private void sendResult(){
        JSONObject resp = new JSONObject();
        resp.put("event", "result");
        resp.put("loser", loser);
        sendAllMessage(resp.toJSONString());
    }
    // 改进健康值同步方法，添加玩家ID
    public void checkHealthSync() {
        JSONObject healthSync = new JSONObject();
        healthSync.put("event", "health-sync");
        healthSync.put("a_id", playerA.getId());
        healthSync.put("a_health", playerA.getHealth());
        healthSync.put("b_id", playerB.getId());
        healthSync.put("b_health", playerB.getHealth());
        healthSync.put("c_id", playerC.getId());
        healthSync.put("c_health", playerC.getHealth());
        sendAllMessage(healthSync.toJSONString());
    }
    
    @Override
    public void run() {
        try {
            // 初始位置通知 - 游戏开始时发送一次
            JSONObject initResp = new JSONObject();
            initResp.put("event", "init-positions");
            initResp.put("a_id", playerA.getId());
            initResp.put("a_x", playerA.getX());
            initResp.put("a_y", playerA.getY());
            initResp.put("b_id", playerB.getId());
            initResp.put("b_x", playerB.getX());
            initResp.put("b_y", playerB.getY());
            initResp.put("c_id", playerC.getId());
            initResp.put("c_x", playerC.getX());
            initResp.put("c_y", playerC.getY());
            sendAllMessage(initResp.toJSONString());
            
            // 游戏开始前先同步一次健康值
            checkHealthSync();
            
            int healthSyncCounter = 0; // 健康同步计数器
            
            while (status.equals("playing")) {
                // 更新所有玩家位置
                playerA.updatePosition();
                playerB.updatePosition();
                playerC.updatePosition();

                // 广播位置信息
                JSONObject resp = new JSONObject();
                resp.put("event", "update");
                resp.put("a_id", playerA.getId());
                resp.put("a_x", playerA.getX());
                resp.put("a_y", playerA.getY());
                resp.put("b_id", playerB.getId());
                resp.put("b_x", playerB.getX());
                resp.put("b_y", playerB.getY());
                resp.put("c_id", playerC.getId());
                resp.put("c_x", playerC.getX());
                resp.put("c_y", playerC.getY());
                sendAllMessage(resp.toJSONString());
                
                // 每隔20帧同步一次健康值，确保所有客户端状态一致
                healthSyncCounter++;
                if (healthSyncCounter >= 20) {
                    checkHealthSync();
                    healthSyncCounter = 0;
                }

                try {
                    Thread.sleep(50); // 控制更新频率
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            
            // 如果游戏已经结束（通过checkGameOver确定了胜负），发送结果
            if (status.equals("finished") && !loser.isEmpty()) {
                sendResult();
            }
        } catch (Exception e) {
            // 捕获所有异常，防止游戏线程意外终止
            e.printStackTrace();
        }
    }
}
